﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CarRent.DAL;
using CarRent.BL.Models;

namespace CarRent.BL
{
    public class BookingImpl : BaseImpl
    {
        public bool InsertBooking(BookingInfo bookingInfo)
        {
            try
            {
                using (Car4RentDataContext db = new Car4RentDataContext(ConnectString))
                {
                    db.Bookings.InsertOnSubmit(new Booking
                    {
                        RequestBy = bookingInfo.RequestBy,
                        RequestFor = bookingInfo.RequestFor,
                        CarID = bookingInfo.CarID,
                        FromDate = bookingInfo.FromDateTime,
                        ToDate = bookingInfo.ToDateTime,
                        Destination = bookingInfo.Destination,
                        Purpose = bookingInfo.Purpose,
                        CreatedDate = DateTime.Now
                    });
                    db.SubmitChanges();

                    return true;
                }
            }
            catch (Exception)
            {
                return false;
            }
        }

        public bool UpdateBooking(BookingInfo bookingInfo)
        {
            try
            {
                using (Car4RentDataContext db = new Car4RentDataContext(ConnectString))
                {
                    var booking = db.Bookings.SingleOrDefault(x => x.BookingID == bookingInfo.BookingID);
                    if (booking == null)
                        return false;

                    booking.StartKm = bookingInfo.StartKM;
                    booking.EndKm = bookingInfo.EndKM;
                    booking.DepartTime = bookingInfo.DepartDateTime;
                    booking.ArrivalTime = bookingInfo.ArrivalDateTime;
                    booking.Remark = bookingInfo.Remark;
                    booking.IsApproval = bookingInfo.IsApproval;
                    booking.CarID = bookingInfo.CarID;

                    db.SubmitChanges();

                    return true;
                }
            }
            catch (Exception)
            {
                return false;
            }
        }

        public BookingInfo GetBooking(int bookingId)
        {
            try
            {
                using (Car4RentDataContext db = new Car4RentDataContext(ConnectString))
                {
                    var booking = db.Bookings.SingleOrDefault(x => x.BookingID == bookingId);
                    if (booking == null)
                        return new BookingInfo();
                    return new BookingInfo(booking);
                }
            }
            catch (Exception)
            {
                return new BookingInfo();
            }
        }

        public IList<BookingInfo> GetBookings(string type, string keyword, DateTime? fromDate, DateTime? toDate, int? pageNumber, int? pageSize, out int count, out int countPending, out int countApproval, out int countDeleted)
        {
            count = 0;
            countPending = 0;
            countApproval = 0;
            countDeleted = 0;

            try
            {
                using (Car4RentDataContext db = new Car4RentDataContext(ConnectString))
                {
                    var bookings = db.Bookings.Where(x => x.User.FullName.Contains(keyword) || x.Destination.Contains(keyword));
                    //if (fromDate.HasValue)
                    //    bookings = bookings.Where(x => x.FromDate >= fromDate.Value);
                    //if (toDate.HasValue)
                    //    bookings = bookings.Where(x => x.ToDate >= toDate.Value);

                    countPending = bookings.Count(x => !x.IsApproval && !x.IsDeleted);
                    countApproval = bookings.Count(x => x.IsApproval && !x.IsDeleted);
                    countDeleted = bookings.Count(x => x.IsDeleted);

                    switch (type.ToLower())
                    {
                        case "pending":
                            bookings = bookings.Where(x => !x.IsApproval && !x.IsDeleted);
                            break;
                        case "approved":
                            bookings = bookings.Where(x => x.IsApproval && !x.IsDeleted);
                            break;
                        case "deleted":
                            bookings = bookings.Where(x => x.IsDeleted);
                            break;
                        default:
                            bookings = bookings.Where(x => !x.IsDeleted);
                            break;
                    }

                    count = bookings.Count();
                    bookings = bookings.OrderByDescending(x => x.CreatedDate);
                    if (pageNumber.HasValue && pageSize.HasValue)
                        return bookings.PageIQuery(pageNumber.Value, pageSize.Value).Select(x => new BookingInfo(x)).ToList();

                    return bookings.Select(x => new BookingInfo(x)).ToList();
                }
            }
            catch (Exception)
            {
                return new List<BookingInfo>();
            }
        }

        public IList<EventInfo> GetEvents(DateTime? fromDate, DateTime? toDate)
        {
            try
            {
                using (Car4RentDataContext db = new Car4RentDataContext(ConnectString))
                {
                    var bookings = db.Bookings.Where(x => x.IsApproval && !x.IsDeleted
                        && ((x.FromDate >= fromDate && x.FromDate <= toDate) ||
                        (x.ToDate >= fromDate && x.ToDate <= toDate)));

                    return bookings.Select(x => new EventInfo(x, x.Car.CarName)).ToList();
                }
            }
            catch (Exception)
            {
                return new List<EventInfo>();
            }
        }

        public bool DeleteBookings(IList<int> bookingIds, bool delete)
        {
            try
            {
                using (Car4RentDataContext db = new Car4RentDataContext(ConnectString))
                {
                    foreach (var item in bookingIds)
                    {
                        var query = db.Bookings.SingleOrDefault(x => x.BookingID == item);
                        if (query == null) continue;
                        query.IsDeleted = delete;
                        if (!delete)
                            query.IsApproval = false;
                    }

                    db.SubmitChanges();

                    return true;
                }
            }
            catch (Exception)
            {
                return false;
            }
        }

        public bool DestroyBookings(IList<int> bookingIds, bool delete)
        {
            try
            {
                using (Car4RentDataContext db = new Car4RentDataContext(ConnectString))
                {
                    foreach (var item in bookingIds)
                    {
                        var query = db.Bookings.SingleOrDefault(x => x.BookingID == item);
                        if (query == null) continue;
                        db.Bookings.DeleteOnSubmit(query);
                    }

                    db.SubmitChanges();

                    return true;
                }
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}
